package jp.co.toshiba.ffsa.action.common;

import java.util.ArrayList;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import jp.co.toshiba.ffsa.dto.LoginDto;
import jp.co.toshiba.ffsa.dto.SessionDto;
import jp.co.toshiba.ffsa.mail.SendMaiMail;
import jp.co.toshiba.ffsa.service.common.CommonService;
import jp.co.toshiba.ffsa.service.common.ConstantValue;
import jp.co.toshiba.ffsa.service.common.ProjectService;

import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.seasar.extension.jdbc.exception.SOptimisticLockException;
import org.seasar.mai.mail.MailAddress;
import org.seasar.struts.annotation.Execute;
import org.seasar.struts.util.ActionMessagesUtil;
import org.seasar.struts.util.MessageResourcesUtil;
import org.seasar.struts.util.RequestUtil;

import com.ozacc.mail.MailSendException;

/**
 * actionスーパークラス
 * @author npc
 */
public class CommonAction {
    /** TOPページ */
    protected final String topTransition = "/cstp/cstp101/";

    /** 汎用エラー画面表示メッセージID(タイトル用) */
    public String genericErrorTitleMessageID = "";
    /** 汎用エラー画面表示メッセージID(内容) */
    public String genericErrorContentsMessageID = "";

    /** サーブレットリクエスト */
    @Resource
    protected HttpServletRequest request;

    @Execute(validator = false)
    public String index() throws Exception{return null;}

    /**
     * ログイン済判定処理
     * @param sessionID セッションID
     * @return boolean true:ログインしている false:ログインしていない
     */
    protected boolean judgeLogin(String sessionID){
        if(((LoginDto)RequestUtil.getRequest().getSession().getAttribute("login_dto")) != null && sessionID.equals(RequestUtil.getRequest().getSession().getId())){
            return true;
        }else{
            ActionMessages errors = new ActionMessages();
            errors.add("nologin", new ActionMessage("errors.nologin"));
            ActionMessagesUtil.saveErrors(request, errors);
            return false;
        }
    }

    /**
     * リファラ判定処理
     * @return boolean true:正常 false:不正
     */
    protected boolean judgeRefferer(){
        if(RequestUtil.getRequest().getHeader("Referer") != null && !RequestUtil.getRequest().getHeader("Referer").equals("")){
            return true;
        }else{
            ActionMessages errors = new ActionMessages();
            errors.add("refferer", new ActionMessage("errors.refferer"));
            ActionMessagesUtil.saveErrors(request, errors);
            return false;
        }
    }

    /**
     * セッションタイムアウト判定処理
     * @return boolean true:正常 false:タイムアウト
     */
    protected boolean judgeSession(){
        if(((SessionDto)RequestUtil.getRequest().getSession().getAttribute("session_dto")) != null){
            return true;
        }else{
            ActionMessages errors = new ActionMessages();
            errors.add("timeout", new ActionMessage("errors.timeout"));
            ActionMessagesUtil.saveErrors(request, errors);
            return false;
        }
    }

    /**
     * セッションタイムアウト判定処理
     * @param sessionID セッションID
     * @return boolean true:正常 false:タイムアウト
     */
    protected boolean judgeSession(String sessionID){
        if(sessionID.equals(RequestUtil.getRequest().getSession().getId())){
            return true;
        }else{
            ActionMessages errors = new ActionMessages();
            errors.add("timeout", new ActionMessage("errors.timeout"));
            ActionMessagesUtil.saveErrors(request, errors);
            return false;
        }
    }

    /**
     * 操作ログ登録
     * @param screenID   画面ID
     * @param methodName メソッド名
     * @param parameters 画面パラメータ(1つ目のArrayList:パラメータ名 2つ目のArrayList:パラメータ) 登録系以外(初期表示等)の場合はnull
     * @throws Exception
     */
    protected void entryOperationHistory(String screenID, String methodName, ArrayList<ArrayList<String>> parameters, String result) throws Exception{
        CommonService service = new CommonService();
        LoginDto dto = ((LoginDto)RequestUtil.getRequest().getSession().getAttribute("login_dto"));
        String userID = "";
        if(dto != null){userID = dto.getUserID();}
        String ipAddress = RequestUtil.getRequest().getRemoteAddr();
        String sessionID = RequestUtil.getRequest().getSession().getId();

        String parameter = "";
        if(parameters != null){
            for(int i=0; i<parameters.get(0).size(); i++){
                parameter = parameter.concat(parameters.get(0).get(i) + ":" + parameters.get(1).get(i) + "\r\n");
            }
        }

        service.entryOperationHistory(userID, ipAddress, sessionID, screenID, methodName, result, parameter);
    }

    /**
     * 操作ログ登録
     * @param screenID   画面ID
     * @param methodName メソッド名
     * @param parameters 画面パラメータ(1つ目のArrayList:パラメータ名 2つ目のArrayList:パラメータ) 登録系以外(初期表示等)の場合はnull
     * @param userID ユーザID
     * @throws Exception
     */
    protected void entryOperationHistory(String screenID, String methodName, ArrayList<ArrayList<String>> parameters, String result, String userID) throws Exception{
        CommonService service = new CommonService();
        String ipAddress = RequestUtil.getRequest().getRemoteAddr();
        String sessionID = RequestUtil.getRequest().getSession().getId();

        String parameter = "";
        if(parameters != null){
            for(int i=0; i<parameters.get(0).size(); i++){
                parameter = parameter.concat(parameters.get(0).get(i) + ":" + parameters.get(1).get(i) + "\r\n");
            }
        }

        service.entryOperationHistory(userID, ipAddress, sessionID, screenID, methodName, result, parameter);
    }

    /**
     * 例外エラー時のログを出力する
     * @param errorContents ログ出力内容
     */
    protected void errorLogWriter(Exception e, String methodName, String screenID){
        CommonService service = new CommonService();
        String errorContents = "";
        // 出力するエラーログ作成
        // ユーザーID
        errorContents = errorContents.concat("\r\n" + MessageResourcesUtil.getMessage("errorLogTitleUserID"));
        LoginDto dto = (LoginDto)RequestUtil.getRequest().getSession().getAttribute("login_dto");
        if(dto != null && dto.getUserID() != null){
            errorContents = errorContents.concat(dto.getUserID());
        }
        errorContents = errorContents.concat("\r\n");
        // IPアドレス
        errorContents = errorContents.concat(MessageResourcesUtil.getMessage("errorLogTitleIPAddress") + RequestUtil.getRequest().getRemoteAddr() + "\r\n");
        // セッションID
        errorContents = errorContents.concat(MessageResourcesUtil.getMessage("errorLogTitleSessionID") + RequestUtil.getRequest().getSession(true).getId() + "\r\n");
        // 画面ID
        errorContents = errorContents.concat(MessageResourcesUtil.getMessage("errorLogTitleScreenID") + screenID + "\r\n");
        // メソッド名
        errorContents = errorContents.concat(MessageResourcesUtil.getMessage("errorLogTitleMethod") + methodName + "\r\n");
        // スタックトレース
        errorContents = errorContents.concat(e.getMessage() + "\r\n");
        errorContents = errorContents.concat(e.toString() + "\r\n");
        for(int i=0; i<e.getStackTrace().length; i++){
            errorContents = errorContents.concat(e.getStackTrace()[i].toString() + "\r\n");
        }

        service.errorLogWriter(errorContents);
    }

    /**
    * メール送信
    */
    protected boolean sendMail() throws Exception{
        boolean successFlag = false;
        try {
            // メール情報をセット
            SendMaiMail sendMaiMail = new SendMaiMail();

            // 送信元メールアドレス(From)
            // 送信元メールアドレス(From)
            String mailAddressFrom = MessageResourcesUtil.getMessage("mail_address_from");
            sendMaiMail.setMailAddressFrom(mailAddressFrom);

            MailAddress[] sendMailAddressTo = new MailAddress[1];
            sendMailAddressTo[0] = new MailAddress("sano@nihon-protec.co.jp","");

            // 送信先メールアドレス(To)
            sendMaiMail.setMailAddressTo(sendMailAddressTo);

            // 送信先メールアドレス(Cc)
            MailAddress[] sendMailAddressCc = new MailAddress[1];
            sendMailAddressCc[0] = new MailAddress("hikita@nihon-protec.co.jp","");
            sendMaiMail.setMailAddressCc(sendMailAddressCc);

            // 送信先メールアドレス(Bcc)
            MailAddress[] sendMailAddressBcc = new MailAddress[1];
            sendMailAddressBcc[0] = new MailAddress("tokushou@nihon-protec.co.jp","");
            sendMaiMail.setMailAddressBcc(sendMailAddressBcc);

            // 送信
            successFlag = sendMaiMail.sendMail(ConstantValue.testMail);

            if(!successFlag){
                return false;
            }

        }catch(MailSendException m){
            return false;
        }catch(Exception e){
            e.printStackTrace();
            throw e;
        }
        return true;
    }

    /**
     * 指定されたプロジェクトをロックします
     * 失敗した場合は排他エラーなのでActionMessagesに排他エラーメッセージを追加します
     * @param projectId
     * @param version
     * @return ロックに成功した場合はtrue
     */
    protected boolean lockProject(String projectId, Integer version) {
        ProjectService projectService = new ProjectService();
        try {
            projectService.lock(projectId, version);
        } catch (SOptimisticLockException sole) {
            setVersionErrorMessageToActionMessages();
            return false;
        }
        return true;
    }

    /**
     * 指定されたプロジェクトのロック状況を確認します
     * ロックされている場合はActionMessagesに排他エラーメッセージを追加します
     * @param projectId
     * @param version
     * @return プロジェクトがロックされている場合はtrue
     */
    protected boolean isProjectLocked(String projectId, Integer version) {
        ProjectService projectService = new ProjectService();
        boolean isLocked = projectService.isLocked(projectId, version);
        if (isLocked) {
            setVersionErrorMessageToActionMessages();
            return true;
        }
        return false;
    }

    protected void setVersionErrorMessageToActionMessages() {
        ActionMessages messages = new ActionMessages();
        messages.add("versionCheckFailed", new ActionMessage("errors.version", true));
        ActionMessagesUtil.addErrors(RequestUtil.getRequest().getSession(true), messages);
    }

}
